package org.rency.ues.dal.repository.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.rency.common.sequence.service.SequenceRepository;
import org.rency.ues.dal.dao.EncryptDataDao;
import org.rency.ues.dal.entity.DataHashDO;
import org.rency.ues.dal.entity.EncryptDataDO;
import org.rency.ues.dal.repository.DataHashRepository;
import org.rency.ues.dal.repository.EncryptDataRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

public class EncryptDataRepositoryImpl implements EncryptDataRepository {
	
	private static final Logger logger = LoggerFactory.getLogger(EncryptDataRepositoryImpl.class);

	public static final String SEQ_ENCRYPT_DATA_NAME = "TICKET";
	public static final String ENCRYPT_DATA_PREFIX = "P";
	
	private EncryptDataDao                encryptDataDao;
	
	private SequenceRepository          sequenceRepository;
	
	private DataHashRepository          dataHashRepository;
	
	private TransactionTemplate         transactionTemplate;
	
	@Override
	public EncryptDataDO get(int id) {
		return encryptDataDao.get(id);
	}

	@Override
	public EncryptDataDO getByTicket(String ticket) {
		return encryptDataDao.getByTicket(ticket);
	}

	@Override
	public boolean delete(int id) {
		return encryptDataDao.delete(id) == 1;
	}

	@Override
	public boolean deleteByTicket(String ticket) {
		return encryptDataDao.deleteByTicket(ticket) == 1;
	}

	@Override
	public boolean save(EncryptDataDO entity) {
		return encryptDataDao.insert(entity) == 1;
	}

	@Override
	public String genTicketId() {
		return ENCRYPT_DATA_PREFIX+sequenceRepository.next(SEQ_ENCRYPT_DATA_NAME);
	}

	public void setEncryptDataDao(EncryptDataDao encryptDataDao) {
		this.encryptDataDao = encryptDataDao;
	}
	
	public void setSequenceRepository(SequenceRepository sequenceRepository) {
		this.sequenceRepository = sequenceRepository;
	}

	/**
	 * 获取到期待清理数据
	 * </br>Created on 2016年5月4日
	 * @return
	 */
	public List<EncryptDataDO> getWaitExpireDate(int pageSize,int pageNo){
		Map<String, Object> param = new HashMap<String, Object>();
		param.put("offset", (pageNo-1)*pageSize);
		param.put("pageSize", pageSize);
		return encryptDataDao.getWaitExpireDate(param);
	}

	public void setDataHashRepository(DataHashRepository dataHashRepository) {
		this.dataHashRepository = dataHashRepository;
	}

	public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
		this.transactionTemplate = transactionTemplate;
	}

	@Override
	public boolean deleteWithRela(final String ticket) {
		return transactionTemplate.execute(new TransactionCallback<Boolean>() {
			@Override
			public Boolean doInTransaction(TransactionStatus status) {
				Object savePoint = status.createSavepoint();
				try{
					if(deleteByTicket(ticket)){
						if(dataHashRepository.deleteByTicket(ticket)){
							return true;
						}
					}
				}catch(Exception e){
					logger.error("删除数据失败.Ticket={}.",ticket,e);
					status.rollbackToSavepoint(savePoint);
				}finally {
					status.releaseSavepoint(savePoint);
					status.flush();
				}
				return false;
			}
		});
	}

	@Override
	public boolean saveWithRela(final EncryptDataDO entity, final String dataHashString) {
		return transactionTemplate.execute(new TransactionCallback<Boolean>() {
			@Override
			public Boolean doInTransaction(TransactionStatus status) {
				Object savePoint = status.createSavepoint();
				try{
					if(save(entity)){
						DataHashDO dataHash = new DataHashDO();
						dataHash.setHash(dataHashString);
						dataHash.setTicket(entity.getTicket());
						if(dataHashRepository.save(dataHash)){
							return true;
						}
					}
				}catch(Exception e){
					logger.error("保存数据失败.Ticket={}.",entity.getTicket(),e);
					status.rollbackToSavepoint(savePoint);
				}finally {
					status.releaseSavepoint(savePoint);
					status.flush();
				}
				return false;
			}
		});
	}
}
